package auctionhaus



import org.junit.*
import grails.test.mixin.*

@TestFor(ListingController)
@Mock(Listing)
class ListingControllerTests {

	int unique = 0;

	def populateValidParams(params) {
		assert params != null

		mockDomain(Customer)

		Customer seller = new Customer()
		seller.emailAddress="mark"+ unique +"@live.com"
		seller.password="132242"
		unique++;


		assertNotNull(seller.save(failOnError:true))


		params["name"] = "This Listing";
		params["endDateTime"] = (new Date())+1
		params["startingPrice"] = 1.0f
		params["seller.id"] = seller.id
	}

	void testIndex() {
		controller.index()
		assert "/listing/list" == response.redirectedUrl
	}

	void testList() {

		def model = controller.list()

		assert model.listingInstanceList.size() == 0
		assert model.listingInstanceTotal == 0
	}

	void testCreate() {
		def model = controller.create()

		assert model.listingInstance != null
	}

	void testSave() {
		controller.save()

		assert model.listingInstance != null
		assert view == '/listing/create'

		response.reset()

		populateValidParams(params)
		controller.save()

		assert response.redirectedUrl == '/listing/show/1'
		assert controller.flash.message != null
		assert Listing.count() == 1
	}

	void testShow() {
		controller.show()

		assert flash.message != null
		assert response.redirectedUrl == '/listing/list'


		populateValidParams(params)
		def listing = new Listing(params)

		assert listing.save() != null

		params.id = listing.id

		def model = controller.show()

		assert model.listingInstance == listing
	}

	void testEdit() {
		controller.edit()

		assert flash.message != null
		assert response.redirectedUrl == '/listing/list'


		populateValidParams(params)
		def listing = new Listing(params)

		assert listing.save() != null

		params.id = listing.id

		def model = controller.edit()

		assert model.listingInstance == listing
	}

	void testUpdate() {
		controller.update()

		assert flash.message != null
		assert response.redirectedUrl == '/listing/list'

		response.reset()


		populateValidParams(params)
		def listing = new Listing(params)

		assert listing.save() != null

		// test invalid parameters in update
		params.id = listing.id
		params.name = "This Listing"
		params.endDateTime = new Date() - 1
		params.startingPrice = 2

		controller.update()

		assert view == "/listing/edit"
		assert model.listingInstance != null

		listing.clearErrors()

		populateValidParams(params)
		controller.update()

		assert response.redirectedUrl == "/listing/show/$listing.id"
		assert flash.message != null

		//test outdated version number
		response.reset()
		listing.clearErrors()

		populateValidParams(params)
		params.id = listing.id
		params.version = -1
		controller.update()

		assert view == "/listing/edit"
		assert model.listingInstance != null
		assert model.listingInstance.errors.getFieldError('version')
		assert flash.message != null
	}

	void testDelete() {
		controller.delete()
		assert flash.message != null
		assert response.redirectedUrl == '/listing/list'

		response.reset()

		populateValidParams(params)
		def listing = new Listing(params)

		assert listing.save() != null
		assert Listing.count() == 1

		params.id = listing.id

		controller.delete()

		assert Listing.count() == 0
		assert Listing.get(listing.id) == null
		assert response.redirectedUrl == '/listing/list'
	}

	//L-7: The detail page for the listing allows a new bid to be placed (unit test of the controller action that handles this requirement)
	void testCreateBidFromController() {

		controller.show()

		assert flash.message != null
		assert response.redirectedUrl == '/listing/list'

		populateValidParams(params)
		def listing = new Listing(params)

		assert listing.save() != null

		params.id = listing.id

		def model = controller.show()

		assert model.listingInstance == listing

		response.reset()

		controller.createBid()
		assert response.redirectedUrl .startsWith( '/bid/create' )

	}

	//L-8: Validation errors will be displayed on the listing detail page if an added bid does not pass validation (unit test of the controller action that handles this requirement)
	void testCreateBidValidation() {

		mockDomain(Bid)
		mockDomain(Customer)
		def bidController = mockController(BidController)

		//need some existing data
		Customer seller = new Customer()
		seller.emailAddress="mark@live.com"
		seller.password="132242"

		Customer bidder = new Customer()
		bidder.emailAddress="earl@live.com"
		bidder.password="132242"

		Listing listing = new Listing()
		listing.startingPrice = 1f
		listing.endDateTime = new Date() + 1
		listing.name = "This Thing"

		seller.addToListings(listing)

		Bid b = new Bid(amount: 2.00f)
		b.bidder = bidder;
		b.listing = listing;

		assertNotNull(seller.save())
		assertNotNull(listing.save())
		assertNotNull(bidder.save())
		assertNotNull(b.save(failOnError:true))

		params.id = listing.id

		def model = controller.show()

		assert model.listingInstance == listing

		response.reset()

		controller.createBid()
		assert response.redirectedUrl .startsWith( '/bid/create' )

		response.reset()
		
		params["listing.id"] = listing.id
		params["bidder.id"] = b.id
		params["amount"] = -10f  //this is invalid
		bidController.save()
		
		//we are back to the listingController
		assert response.redirectedUrl .startsWith( '/listing/show/'+listing.id )
		assert flash.message == "bids.invalid.amount"

	}
}
